#include <iostream>
#include <string>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

#define CREATOR "creater"
#define USER "user"

#include "public.hpp"

class shm
{
private:
    void CreatShm()
    {
        _shmid = shmget(_key, DEFAULT_SIZE, IPC_CREAT | IPC_EXCL | 0666);
        
        std::cout << "creat shm success!" << std::endl;
    }

    void Getshm()
    {
        _shmid = shmget(_key, DEFAULT_SIZE, IPC_CREAT);

        std::cout << "get shm success!" << std::endl;
    }

    void Attach()
    {
        // 让进程与共享内存关联
        void* adder = shmat(_shmid, NULL, 0);
        if(adder == (void*)-1)
            ERR("shmat");
        _start_mm = adder;

        std::cout << "attach success!" << std::endl;
    }

    void Detach()
    {
        int n = shmdt(_start_mm);
        if(n == -1)
            ERR("shmdt");
        
        std::cout << "detach success!" << std::endl;
    }

    void Destory()
    {
        shmctl(_shmid, IPC_RMID, NULL);
        
        std::cout << "delete shm sucess!" << std::endl;
    }

public:
    shm(const std::string &pathname, const int proj_id, const std::string &usertype)
        : _usertype(usertype), _start_mm(nullptr)
    {
        // 获取key值
        _key = ftok(pathname.c_str(), proj_id);
        if (_key == -1)
            ERR("key");

        // 创建/获取共享内存
        if (usertype == CREATOR)
            CreatShm();
        else if (usertype == USER)
            Getshm();
        else
            std::cout << "usertype error!" << std::endl;
        
        // 让进程与共享内存关联
        Attach();
    }

    ~shm() 
    {
        Detach();
        if(_usertype == CREATOR)
            Destory();
    }

    void* GetAdder()
    {
        return _start_mm;
    }

private:
    int _shmid;
    key_t _key;
    void *_start_mm;
    const std::string _usertype;
};